using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using SeataNet.Core.Attributes;
using SeataNet.Core.Context;
using SeataNet.Core.Exceptions;
using SeataNet.Core.Interceptors;
using System.Reflection;

namespace SeataNet.Core.TCC
{
    /// <summary>
    /// TCC模式事务拦截器
    /// </summary>
    public class TccMethodInterceptor : IMethodInterceptor
    {
        private readonly ITccTransactionManager _transactionManager;
        private readonly ILogger<TccMethodInterceptor> _logger;
        private readonly IServiceProvider _serviceProvider;

        public TccMethodInterceptor(
            ITccTransactionManager transactionManager,
            ILogger<TccMethodInterceptor> logger,
            IServiceProvider serviceProvider)
        {
            _transactionManager = transactionManager;
            _logger = logger;
            _serviceProvider = serviceProvider;
        }

        public async Task<object> InterceptAsync(IMethodInvocation invocation)
        {
            var method = invocation.Method;
            var attributes = method.GetCustomAttributes<TccTransactionalAttribute>(true);
            
            if (!attributes.Any())
            {
                // 检查类级别的属性
                attributes = method.DeclaringType?.GetCustomAttributes<TccTransactionalAttribute>(true) ?? 
                           Enumerable.Empty<TccTransactionalAttribute>();
            }

            if (!attributes.Any())
            {
                // 没有TCC事务注解，直接执行方法
                return await invocation.ProceedAsync();
            }

            var transactionAttribute = attributes.First();
            return await ExecuteInTccTransactionAsync(invocation, transactionAttribute);
        }

        private async Task<object> ExecuteInTccTransactionAsync(
            IMethodInvocation invocation, 
            TccTransactionalAttribute attribute)
        {
            var xid = RootContext.GetXid();
            var method = invocation.Method;
            var className = method.DeclaringType?.Name;
            var methodName = method.Name;

            _logger.LogDebug($"开始TCC事务: Class={className}, Method={methodName}, Timeout={attribute.TimeoutMs}");

            // 如果已经在全局事务中，则直接执行方法
            if (!string.IsNullOrEmpty(xid))
            {
                _logger.LogDebug($"已在全局事务中，直接执行方法: XID={xid}");
                return await invocation.ProceedAsync();
            }

            // 开始新的全局事务
            var beginResult = await _transactionManager.BeginAsync(attribute.TimeoutMs, attribute.Name);
            
            if (!beginResult.Success)
            {
                _logger.LogError($"开始TCC事务失败: Message={beginResult.Message}");
                throw new TransactionException($"开始TCC事务失败: {beginResult.Message}");
            }

            var newXid = beginResult.Xid;
            RootContext.Bind(newXid);

            try
            {
                // 执行目标方法
                var result = await invocation.ProceedAsync();
                
                // 提交全局事务
                var commitResult = await _transactionManager.CommitAsync(newXid);
                
                if (!commitResult.Success)
                {
                    _logger.LogError($"提交TCC事务失败: XID={newXid}, Message={commitResult.Message}");
                    throw new TransactionException($"提交TCC事务失败: {commitResult.Message}");
                }

                _logger.LogDebug($"TCC事务已提交: XID={newXid}");
                return result;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"TCC事务执行异常，开始回滚: XID={newXid}");
                
                // 回滚全局事务
                var rollbackResult = await _transactionManager.RollbackAsync(newXid);
                
                if (!rollbackResult.Success)
                {
                    _logger.LogError($"回滚TCC事务失败: XID={newXid}, Message={rollbackResult.Message}");
                }
                else
                {
                    _logger.LogDebug($"TCC事务已回滚: XID={newXid}");
                }
                
                throw;
            }
            finally
            {
                // 清理上下文
                RootContext.Unbind();
            }
        }
    }

    /// <summary>
    /// TCC模式事务切面
    /// </summary>
    public class TccTransactionAspect
    {
        private readonly ITccTransactionManager _transactionManager;
        private readonly ILogger<TccTransactionAspect> _logger;

        public TccTransactionAspect(
            ITccTransactionManager transactionManager,
            ILogger<TccTransactionAspect> logger)
        {
            _transactionManager = transactionManager;
            _logger = logger;
        }

        public async Task<T> ExecuteAsync<T>(Func<Task<T>> action, TccTransactionalAttribute attribute)
        {
            var xid = RootContext.GetXid();

            _logger.LogDebug($"开始TCC事务: Timeout={attribute.TimeoutMs}");

            // 如果已经在全局事务中，则直接执行方法
            if (!string.IsNullOrEmpty(xid))
            {
                _logger.LogDebug($"已在全局事务中，直接执行方法: XID={xid}");
                return await action();
            }

            // 开始新的全局事务
            var beginResult = await _transactionManager.BeginAsync(attribute.TimeoutMs, attribute.Name);
            
            if (!beginResult.Success)
            {
                _logger.LogError($"开始TCC事务失败: Message={beginResult.Message}");
                throw new TransactionException($"开始TCC事务失败: {beginResult.Message}");
            }

            var newXid = beginResult.Xid;
            RootContext.Bind(newXid);

            try
            {
                // 执行目标方法
                var result = await action();
                
                // 提交全局事务
                var commitResult = await _transactionManager.CommitAsync(newXid);
                
                if (!commitResult.Success)
                {
                    _logger.LogError($"提交TCC事务失败: XID={newXid}, Message={commitResult.Message}");
                    throw new TransactionException($"提交TCC事务失败: {commitResult.Message}");
                }

                _logger.LogDebug($"TCC事务已提交: XID={newXid}");
                return result;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"TCC事务执行异常，开始回滚: XID={newXid}");
                
                // 回滚全局事务
                var rollbackResult = await _transactionManager.RollbackAsync(newXid);
                
                if (!rollbackResult.Success)
                {
                    _logger.LogError($"回滚TCC事务失败: XID={newXid}, Message={rollbackResult.Message}");
                }
                else
                {
                    _logger.LogDebug($"TCC事务已回滚: XID={newXid}");
                }
                
                throw;
            }
            finally
            {
                // 清理上下文
                RootContext.Unbind();
            }
        }

        public async Task ExecuteAsync(Func<Task> action, TccTransactionalAttribute attribute)
        {
            await ExecuteAsync<object>(async () => 
            {
                await action();
                return null;
            }, attribute);
        }
    }

    /// <summary>
    /// TCC模式事务模板
    /// </summary>
    public class TccTransactionTemplate
    {
        private readonly ITccTransactionManager _transactionManager;
        private readonly ILogger<TccTransactionTemplate> _logger;
        private readonly IServiceProvider _serviceProvider;

        public TccTransactionTemplate(
            ITccTransactionManager transactionManager,
            ILogger<TccTransactionTemplate> logger,
            IServiceProvider serviceProvider)
        {
            _transactionManager = transactionManager;
            _logger = logger;
            _serviceProvider = serviceProvider;
        }

        public async Task<T> ExecuteAsync<T>(Func<TccTransactionContext, Task<T>> action, 
            int timeoutMs = 60000, 
            string? name = null)
        {
            var xid = RootContext.GetXid();

            _logger.LogDebug($"开始TCC事务模板: Timeout={timeoutMs}, Name={name}");

            // 如果已经在全局事务中，则直接执行方法
            if (!string.IsNullOrEmpty(xid))
            {
                _logger.LogDebug($"已在全局事务中，直接执行方法: XID={xid}");
                var context = new TccTransactionContext { Xid = xid, Phase = TccTransactionPhase.Try };
                return await action(context);
            }

            // 开始新的全局事务
            var beginResult = await _transactionManager.BeginAsync(timeoutMs, name);
            
            if (!beginResult.Success)
            {
                _logger.LogError($"开始TCC事务失败: Message={beginResult.Message}");
                throw new TransactionException($"开始TCC事务失败: {beginResult.Message}");
            }

            var newXid = beginResult.Xid;
            RootContext.Bind(newXid);

            try
            {
                // 创建事务上下文
                var context = new TccTransactionContext 
                { 
                    Xid = newXid, 
                    TransactionName = name,
                    Timeout = timeoutMs,
                    Status = TccTransactionStatus.Trying,
                    Phase = TccTransactionPhase.Try,
                    StartTime = DateTime.UtcNow
                };
                
                // 执行目标方法
                var result = await action(context);
                
                // 提交全局事务
                var commitResult = await _transactionManager.CommitAsync(newXid);
                
                if (!commitResult.Success)
                {
                    _logger.LogError($"提交TCC事务失败: XID={newXid}, Message={commitResult.Message}");
                    throw new TransactionException($"提交TCC事务失败: {commitResult.Message}");
                }

                _logger.LogDebug($"TCC事务已提交: XID={newXid}");
                return result;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"TCC事务执行异常，开始回滚: XID={newXid}");
                
                // 回滚全局事务
                var rollbackResult = await _transactionManager.RollbackAsync(newXid);
                
                if (!rollbackResult.Success)
                {
                    _logger.LogError($"回滚TCC事务失败: XID={newXid}, Message={rollbackResult.Message}");
                }
                else
                {
                    _logger.LogDebug($"TCC事务已回滚: XID={newXid}");
                }
                
                throw;
            }
            finally
            {
                // 清理上下文
                RootContext.Unbind();
            }
        }

        public async Task ExecuteAsync(Func<TccTransactionContext, Task> action, 
            int timeoutMs = 60000, 
            string? name = null)
        {
            await ExecuteAsync<object>(async context => 
            {
                await action(context);
                return null;
            }, timeoutMs, name);
        }
    }

    /// <summary>
    /// TCC服务基类
    /// </summary>
    public abstract class TccServiceBase : ITccService
    {
        private readonly ILogger _logger;

        protected TccServiceBase(ILogger logger)
        {
            _logger = logger;
        }

        public abstract string ServiceName { get; }

        public async Task<object> TryAsync(TccActionContext actionContext)
        {
            _logger.LogDebug($"执行TCC Try方法: Service={ServiceName}, Method={actionContext.MethodName}");
            
            try
            {
                var result = await DoTryAsync(actionContext);
                _logger.LogDebug($"TCC Try方法执行成功: Service={ServiceName}, Method={actionContext.MethodName}");
                return result;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"TCC Try方法执行失败: Service={ServiceName}, Method={actionContext.MethodName}");
                throw;
            }
        }

        public async Task<bool> ConfirmAsync(TccActionContext actionContext)
        {
            _logger.LogDebug($"执行TCC Confirm方法: Service={ServiceName}, Method={actionContext.MethodName}");
            
            try
            {
                var result = await DoConfirmAsync(actionContext);
                
                if (result)
                {
                    _logger.LogDebug($"TCC Confirm方法执行成功: Service={ServiceName}, Method={actionContext.MethodName}");
                }
                else
                {
                    _logger.LogError($"TCC Confirm方法执行失败: Service={ServiceName}, Method={actionContext.MethodName}");
                }
                
                return result;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"TCC Confirm方法执行异常: Service={ServiceName}, Method={actionContext.MethodName}");
                return false;
            }
        }

        public async Task<bool> CancelAsync(TccActionContext actionContext)
        {
            _logger.LogDebug($"执行TCC Cancel方法: Service={ServiceName}, Method={actionContext.MethodName}");
            
            try
            {
                var result = await DoCancelAsync(actionContext);
                
                if (result)
                {
                    _logger.LogDebug($"TCC Cancel方法执行成功: Service={ServiceName}, Method={actionContext.MethodName}");
                }
                else
                {
                    _logger.LogError($"TCC Cancel方法执行失败: Service={ServiceName}, Method={actionContext.MethodName}");
                }
                
                return result;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"TCC Cancel方法执行异常: Service={ServiceName}, Method={actionContext.MethodName}");
                return false;
            }
        }

        /// <summary>
        /// 执行Try方法的具体实现
        /// </summary>
        /// <param name="actionContext">动作上下文</param>
        /// <returns>Try结果</returns>
        protected abstract Task<object> DoTryAsync(TccActionContext actionContext);

        /// <summary>
        /// 执行Confirm方法的具体实现
        /// </summary>
        /// <param name="actionContext">动作上下文</param>
        /// <returns>Confirm结果</returns>
        protected abstract Task<bool> DoConfirmAsync(TccActionContext actionContext);

        /// <summary>
        /// 执行Cancel方法的具体实现
        /// </summary>
        /// <param name="actionContext">动作上下文</param>
        /// <returns>Cancel结果</returns>
        protected abstract Task<bool> DoCancelAsync(TccActionContext actionContext);
    }
}